package com.abner.basis.readwritelock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁
 *  场景: 对同一份数据多个线程同时进行读写,会出现问题,采用读写锁来解决
 * @author yuhui
 */
public class ReadWriteLockDemo {

    public static void main(String[] args) {
        MapCache mapCache = new MapCache();

        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(() -> {
                mapCache.setData(String.valueOf(finalI),finalI);
            },String.valueOf(i)).start();

        }

        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(() -> {
                mapCache.getData(String.valueOf(finalI));
            },String.valueOf(i)).start();

        }
    }
}

class MapCache {

    private volatile Map<String,Object> map = new HashMap<>();

    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public void setData(String key, Object val) {
        try {
            readWriteLock.writeLock().lock();

            System.out.println(Thread.currentThread().getName()+"正在进行写操作,写的key为:" + key);
            // 写一会
            TimeUnit.SECONDS.sleep(3);

            map.put(key,val);
            System.out.println(Thread.currentThread().getName()+"写入完成:" + key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            readWriteLock.writeLock().unlock();
        }

    }

    public Object getData(String key) {
        try {
            readWriteLock.writeLock().lock();
            System.out.println(Thread.currentThread().getName()+"正在进行读操作,读的key为:" + key);
            // 读一会
            TimeUnit.SECONDS.sleep(3);

            System.out.println(Thread.currentThread().getName()+"读完了为:" + key);
            return map.get(key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            readWriteLock.writeLock().unlock();
        }
        return null;
    }

}
